﻿#include "ssMySQLStmtQuery.h"
//#include "dump/ssException.h"


namespace StarSeeker
{

ssMySQLStmtQuery::ssMySQLStmtQuery()
	:m_stmt(this)
{
}

ssMySQLStmtQuery::~ssMySQLStmtQuery()
{
	StmtExit();
}

void ssMySQLStmtQuery::StmtExit()
{
	m_stmt.Clear();
	std::map<u32, ssMySQLStmt>::iterator itr;
	for (itr=m_stmtMap.begin(); itr!=m_stmtMap.end(); ++itr)
	{
		itr->second.Clear();
	}
	m_stmtMap.clear();
	ssMySQLConnection::Exit();
}

int ssMySQLStmtQuery::Query(const char * pSql, const char * pIn, const char * pOut, u8 resultFlag, i32 num, ...)
{
	if (m_pConnect)
	{
		m_stmt.Clear();
		int ret = m_stmt.PrepareQuery(pIn, pOut, pSql, resultFlag);
		if (ret)
		{
			if (ReconnectTest())
			{
				ret = m_stmt.Prepare();
			}
			else
			{
				return ret;
			}
		}
		if (ret)
			return ret;

		va_list arglist;
		va_start(arglist, num);
		ret = m_stmt.ExecuteQueryVariable(num, arglist);
		va_end(arglist);

		return ret;
	}
	else
	{
		return DB_QUERY_CONNECT_NULL;
	}
}

int ssMySQLStmtQuery::QueryStreaming(const char* pSql, const char* pIn, const char* pOut, u8 resultFlag, u32 len, const char* data)
{
	if (m_pConnect)
	{
		m_stmt.Clear();
		int ret = m_stmt.PrepareQuery(pIn, pOut, pSql, resultFlag);
		if (ret)
		{
			if (ReconnectTest())
			{
				ret = m_stmt.Prepare();
			}
			else
			{
				return ret;
			}
		}
		if (ret)
			return ret;

		ret = m_stmt.ExecuteQueryStream(len, data);
		return ret;
	}
	else
	{
		return DB_QUERY_CONNECT_NULL;
	}
}

std::pair<int, ssLineBuffer&> ssMySQLStmtQuery::GetResultSet()
{
	i32 ret = m_stmt.FormatResult();
	return std::pair<int, ssLineBuffer&>(ret, m_resultSet);
}

std::pair<int, ssLineBuffer&> ssMySQLStmtQuery::GetResultSet(u32 id)
{
	std::pair<int, ssLineBuffer&> ret(0, m_resultSet);
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		m_error = "GetResultSet id not found!";
		ret.first = DB_QUERY_NOT_EXIST;
	}
	else
	{
		ret.first = itr->second.FormatResult();
	}
	return ret;
}

std::pair<int, ssReadBytes> ssMySQLStmtQuery::GetOneResult()
{
	i32 ret = m_stmt.FormatResult();
	std::pair<int, ssReadBytes> rb;
	rb.first = ret;
	ssMySQLConnection::GetOneResult(rb.second);
	return rb;
}

std::pair<int, ssReadBytes> ssMySQLStmtQuery::GetOneResult(u32 id)
{
	std::pair<int, ssReadBytes> rb;
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		m_error = "GetResultSet id not found!";
		rb.first = DB_QUERY_NOT_EXIST;
	}
	else
	{
		rb.first = itr->second.FormatResult();
		if (0==rb.first)
		{
			ssMySQLConnection::GetOneResult(rb.second);
		}
	}
	return rb;
}

int ssMySQLStmtQuery::GetOneResult(ssReadBytes& rb)
{
	i32 ret = m_stmt.FormatResult();
	if (0 == ret)
	{
		ssMySQLConnection::GetOneResult(rb);
	}
	return ret;
}

int ssMySQLStmtQuery::GetOneResult(u32 id, ssReadBytes& rb)
{
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		m_error = "GetResultSet id not found!";
		return DB_QUERY_NOT_EXIST;
	}
	else
	{
		i32 ret = itr->second.FormatResult();
		if (0==ret)
		{
			ssMySQLConnection::GetOneResult(rb);
		}
		return ret;
	}
}

int ssMySQLStmtQuery::PrepareQuery(u32 id, const char* pIn, const char* pOut, const char* pSql, const u8 resultFlag)
{
	ssMySQLStmt stmt(this);
	std::pair<std::map<u32, ssMySQLStmt>::iterator, bool> ret = m_stmtMap.insert(std::pair<u32, ssMySQLStmt>(id, stmt));
	if (ret.second)
	{
		if (m_pConnect)
		{
			int pret = (ret.first->second).PrepareQuery(pIn, pOut, pSql, resultFlag);
			if (pret)
			{
				if (ReconnectTest())
				{
					pret = m_stmt.Prepare();
				}
			}
			return pret;
		}
		else
		{
			return DB_QUERY_CONNECT_NULL;
		}
	}
	else
	{
		return DB_QUERY_NOT_EXIST;
	}
}

int ssMySQLStmtQuery::PrepareQuery(u32 id, const char* pSql, const u8 resultFlag)
{
	ssMySQLStmt stmt(this);
	std::pair<std::map<u32, ssMySQLStmt>::iterator, bool> ret = m_stmtMap.insert(std::pair<u32, ssMySQLStmt>(id, stmt));
	if (ret.second)
	{
		if (m_pConnect)
		{
			int pret = (ret.first->second).PrepareQuery(pSql, resultFlag);
			if (pret)
			{
				if (ReconnectTest())
				{
					pret = m_stmt.Prepare();
				}
			}
			return pret;
		}
		else
		{
			return DB_QUERY_CONNECT_NULL;
		}
	}
	else
	{
		return DB_QUERY_NOT_EXIST;
	}
}

int ssMySQLStmtQuery::QueryByID(u32 id, i32 num, ...)
{
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		return DB_QUERY_NOT_EXIST;
	}
	if (!itr->second.IsPrepared())
	{
		m_error = "ssMySQLStmt:IsPrepared false!";
		//return DB_PREPARE_ERROR;
	}
	if (Connect())
	{
		va_list arglist;
		va_start(arglist, num);
		int ret = itr->second.ExecuteQueryVariable(num, arglist);
		va_end(arglist);
		
		if (ret)
		{
			if (ReconnectTest())
			{
				ret = itr->second.TryExecuteSQLAgain();
			}
		}
		return ret;
	}
	else
	{
		return DB_QUERY_CONNECT_NULL;
	}
}

int ssMySQLStmtQuery::QueryByIDStreaming(u32 id, u32 len, const char* data)
{
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		return DB_QUERY_NOT_EXIST;
	}
	if (!itr->second.IsPrepared())
	{
		m_error = "ssMySQLStmt:IsPrepared false!";
		//return DB_PREPARE_ERROR;
	}
	if (Connect())
	{
		int ret = itr->second.ExecuteQueryStream(len, data);
		if (ret)
		{
			if (ReconnectTest())
			{
				ret = itr->second.TryExecuteSQLAgain();
			}
		}
		return ret;
	}
	else
	{
		return DB_QUERY_CONNECT_NULL;
	}
}

StarSeeker::u8 ssMySQLStmtQuery::GetResultFlag(u32 id)
{
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		return 0;
	}
	else
	{
		return itr->second.GetResultFlag();
	}
}

void ssMySQLStmtQuery::RePrepare()
{
	if (!m_stmtMap.empty())
	{
		std::map<u32, ssMySQLStmt>::iterator itr;
		for (itr = m_stmtMap.begin(); itr != m_stmtMap.end(); ++itr)
		{
			itr->second.ClearResult();
			int pret = itr->second.Prepare();
			if (pret)
			{
				break;
			}
		}
	}
}

}
